//顶点着色器
// import * as vert from "./vert"

import { LeetCode88 } from "./LeetCode88";
import { LeetCode27 } from "./LeetCode27";
import { LeetCode26 } from "./LeetCode26";
import { LeetCode80 } from "./LeetCode80";
import Matrix4 from "./matrix4";
import { LeetCode169 } from "./LeetCode169";
import { LeetCode189 } from "./LeetCode189";
import { LeetCode122 } from "./LeetCode122";
import { LeetCode55 } from "./LeetCode55";
import { MatchMaker } from "./MatchMaker";
import { MatchMaker2 } from "./MatchMaker2";


export default class Main {
    private program: WebGLProgram;
    private translation = [-150, 0, -360];
    private rotation = [0, 0, 0];
    private scale = [1, 1, 1];
    private fov = 60;
    // private resolutionLocation: WebGLUniformLocation = null;
    private positionLocation: number = 0;
    private colorLocation: number = 0;
    private matrixLocation: WebGLUniformLocation = null;
    private positionBuffer: WebGLBuffer = null;
    private colorBuffer: WebGLBuffer = null;

    start() {
        let self = this;
        // Get A WebGL context
        let canvas = document.querySelector("#canvas") as HTMLCanvasElement;
        let gl = canvas.getContext("webgl");
        if (!gl) {
            return;
        }

        // setup GLSL program
        let program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-2d", "fragment-shader-2d"]);
        this.program = program;
        // look up where the vertex data needs to go.
        this.positionLocation = gl.getAttribLocation(program, "a_position");
        this.colorLocation = gl.getAttribLocation(program, "a_color");

        // lookup uniforms
        this.matrixLocation = gl.getUniformLocation(program, "u_matrix");
        // Create a buffer to put positions in
        this.positionBuffer = gl.createBuffer();
        // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
        gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
        // Put geometry data into buffer
        this.setGeometry(gl);

        // Create a buffer to put colors in
        this.colorBuffer = gl.createBuffer();
        // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = colorBuffer)
        gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
        // Put geometry data into buffer
        this.setColors(gl);

        // Draw the scene.
        this.drawScene(gl);

        // Setup a ui.
        webglLessonsUI.setupSlider("#fov", { value: this.fov, slide: updateFov, min: 1, max: 179, step: 1 });
        webglLessonsUI.setupSlider("#x", { value: this.translation[0], slide: updatePosition(0), min: -gl.canvas.width, max: gl.canvas.width });
        webglLessonsUI.setupSlider("#y", { value: this.translation[1], slide: updatePosition(1), min: -gl.canvas.height, max: gl.canvas.height });
        webglLessonsUI.setupSlider("#z", { value: this.translation[2], slide: updatePosition(2), min: -gl.canvas.height, max: gl.canvas.height });
        webglLessonsUI.setupSlider("#angleX", { value: this.rotation[0], slide: updateAngle(0), max: 360 });
        webglLessonsUI.setupSlider("#angleY", { value: this.rotation[1], slide: updateAngle(1), max: 360 });
        webglLessonsUI.setupSlider("#angleZ", { value: this.rotation[2], slide: updateAngle(2), max: 360 });
        webglLessonsUI.setupSlider("#scaleX", { value: this.scale[0], slide: updateScale(0), min: -3, max: 3, step: 0.01, precision: 2 });
        webglLessonsUI.setupSlider("#scaleY", { value: this.scale[1], slide: updateScale(1), min: -3, max: 3, step: 0.01, precision: 2 });
        webglLessonsUI.setupSlider("#scaleZ", { value: this.scale[1], slide: updateScale(2), min: -3, max: 3, step: 0.01, precision: 2 });

        function updateFov(event, ui) {
            self.fov = ui.value;
            self.drawScene(gl);
        }

        function updatePosition(index) {
            return function (event, ui) {
                self.translation[index] = ui.value;
                self.drawScene(gl);
            };
        }

        function updateAngle(index) {
            return function (event, ui) {
                let angleInDegrees = 360 - ui.value;
                self.rotation[index] = angleInDegrees * Math.PI / 180;
                self.drawScene(gl);
            };
        }

        function updateScale(index) {
            return function (event, ui) {
                self.scale[index] = ui.value;
                self.drawScene(gl);
            };
        }

        

    }

    drawScene(gl: WebGLRenderingContext) {
        let glCanvas: HTMLCanvasElement = gl.canvas as HTMLCanvasElement;
        webglUtils.resizeCanvasToDisplaySize(glCanvas);

        // Tell WebGL how to convert from clip space to pixels
        gl.viewport(0, 0, glCanvas.width, glCanvas.height);

        // Clear the canvas.
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        // Turn on culling. By default backfacing triangles
        // will be culled.
        gl.enable(gl.CULL_FACE);

        // Enable the depth buffer
        gl.enable(gl.DEPTH_TEST);

        // Tell it to use our program (pair of shaders)
        gl.useProgram(this.program);

        {
            // Turn on the attribute
            gl.enableVertexAttribArray(this.positionLocation);

            // Bind the position buffer.
            gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);

            // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
            let size = 3;          // 2 components per iteration
            let type = gl.FLOAT;   // the data is 32bit floats
            let normalize = false; // don't normalize the data
            let stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
            let offset = 0;        // start at the beginning of the buffer
            gl.vertexAttribPointer(
                this.positionLocation, size, type, normalize, stride, offset);
        }
        {
            // Turn on the color attribute
            gl.enableVertexAttribArray(this.colorLocation);

            // Bind the color buffer.
            gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);

            // Tell the attribute how to get data out of colorBuffer (ARRAY_BUFFER)
            let size = 3;                 // 3 components per iteration
            let type = gl.UNSIGNED_BYTE;  // the data is 8bit unsigned values
            let normalize = true;         // normalize the data (convert from 0-255 to 0-1)
            let stride = 0;               // 0 = move forward size * sizeof(type) each iteration to get the next position
            let offset = 0;               // start at the beginning of the buffer
            gl.vertexAttribPointer(
                this.colorLocation, size, type, normalize, stride, offset);
        }
        // set the resolution
        // gl.uniform2f(this.resolutionLocation, glCanvas.width, glCanvas.height);

        // Multiply the matrices.
        let aspect = glCanvas.clientWidth / glCanvas.clientHeight;
        let zNear = 1;
        let zFar = 2000;
        let matrix = Matrix4.perspective(this.fov * Math.PI / 180, aspect, zNear, zFar);
        // matrix = Matrix4.multiply(matrix, Matrix4.projection(glCanvas.clientWidth, glCanvas.clientHeight, 400));
        matrix = Matrix4.translate(matrix, this.translation[0], this.translation[1], this.translation[2]);
        matrix = Matrix4.xRotate(matrix, this.rotation[0]);
        matrix = Matrix4.yRotate(matrix, this.rotation[1]);
        matrix = Matrix4.zRotate(matrix, this.rotation[2]);
        matrix = Matrix4.scale(matrix, this.scale[0], this.scale[1], this.scale[2]);

        // Set the matrix.
        let matrix2 = Matrix4.projection(glCanvas.clientWidth, glCanvas.clientHeight, 400);
        gl.uniformMatrix4fv(this.matrixLocation, false, matrix);

        // Draw the geometry.
        let primitiveType = gl.TRIANGLES;
        let offset = 0;
        let count = 16 * 6;  // 6 triangles in the 'F', 3 points per triangle
        gl.drawArrays(primitiveType, offset, count);
    }

    setGeometry(gl: WebGLRenderingContext) {
        gl.bufferData(
            gl.ARRAY_BUFFER,
            new Float32Array([
                // left column front
                0, 0, 0,
                0, 150, 0,
                30, 0, 0,
                0, 150, 0,
                30, 150, 0,
                30, 0, 0,

                // top rung front
                30, 0, 0,
                30, 30, 0,
                100, 0, 0,
                30, 30, 0,
                100, 30, 0,
                100, 0, 0,

                // middle rung front
                30, 60, 0,
                30, 90, 0,
                67, 60, 0,
                30, 90, 0,
                67, 90, 0,
                67, 60, 0,

                // left column back
                0, 0, 30,
                30, 0, 30,
                0, 150, 30,
                0, 150, 30,
                30, 0, 30,
                30, 150, 30,

                // top rung back
                30, 0, 30,
                100, 0, 30,
                30, 30, 30,
                30, 30, 30,
                100, 0, 30,
                100, 30, 30,

                // middle rung back
                30, 60, 30,
                67, 60, 30,
                30, 90, 30,
                30, 90, 30,
                67, 60, 30,
                67, 90, 30,

                // top
                0, 0, 0,
                100, 0, 0,
                100, 0, 30,
                0, 0, 0,
                100, 0, 30,
                0, 0, 30,

                // top rung right
                100, 0, 0,
                100, 30, 0,
                100, 30, 30,
                100, 0, 0,
                100, 30, 30,
                100, 0, 30,

                // under top rung
                30, 30, 0,
                30, 30, 30,
                100, 30, 30,
                30, 30, 0,
                100, 30, 30,
                100, 30, 0,

                // between top rung and middle
                30, 30, 0,
                30, 60, 30,
                30, 30, 30,
                30, 30, 0,
                30, 60, 0,
                30, 60, 30,

                // top of middle rung
                30, 60, 0,
                67, 60, 30,
                30, 60, 30,
                30, 60, 0,
                67, 60, 0,
                67, 60, 30,

                // right of middle rung
                67, 60, 0,
                67, 90, 30,
                67, 60, 30,
                67, 60, 0,
                67, 90, 0,
                67, 90, 30,

                // bottom of middle rung.
                30, 90, 0,
                30, 90, 30,
                67, 90, 30,
                30, 90, 0,
                67, 90, 30,
                67, 90, 0,

                // right of bottom
                30, 90, 0,
                30, 150, 30,
                30, 90, 30,
                30, 90, 0,
                30, 150, 0,
                30, 150, 30,

                // bottom
                0, 150, 0,
                0, 150, 30,
                30, 150, 30,
                0, 150, 0,
                30, 150, 30,
                30, 150, 0,

                // left side
                0, 0, 0,
                0, 0, 30,
                0, 150, 30,
                0, 0, 0,
                0, 150, 30,
                0, 150, 0]),
            gl.STATIC_DRAW);
    }

    // Fill the buffer with colors for the 'F'.
    setColors(gl: WebGLRenderingContext) {
        gl.bufferData(
            gl.ARRAY_BUFFER,
            new Uint8Array([
                // left column front
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,

                // top rung front
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,

                // middle rung front
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,
                200, 70, 120,

                // left column back
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,

                // top rung back
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,

                // middle rung back
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,
                80, 70, 200,

                // top
                70, 200, 210,
                70, 200, 210,
                70, 200, 210,
                70, 200, 210,
                70, 200, 210,
                70, 200, 210,

                // top rung right
                200, 200, 70,
                200, 200, 70,
                200, 200, 70,
                200, 200, 70,
                200, 200, 70,
                200, 200, 70,

                // under top rung
                210, 100, 70,
                210, 100, 70,
                210, 100, 70,
                210, 100, 70,
                210, 100, 70,
                210, 100, 70,

                // between top rung and middle
                210, 160, 70,
                210, 160, 70,
                210, 160, 70,
                210, 160, 70,
                210, 160, 70,
                210, 160, 70,

                // top of middle rung
                70, 180, 210,
                70, 180, 210,
                70, 180, 210,
                70, 180, 210,
                70, 180, 210,
                70, 180, 210,

                // right of middle rung
                100, 70, 210,
                100, 70, 210,
                100, 70, 210,
                100, 70, 210,
                100, 70, 210,
                100, 70, 210,

                // bottom of middle rung.
                76, 210, 100,
                76, 210, 100,
                76, 210, 100,
                76, 210, 100,
                76, 210, 100,
                76, 210, 100,

                // right of bottom
                140, 210, 80,
                140, 210, 80,
                140, 210, 80,
                140, 210, 80,
                140, 210, 80,
                140, 210, 80,

                // bottom
                90, 130, 110,
                90, 130, 110,
                90, 130, 110,
                90, 130, 110,
                90, 130, 110,
                90, 130, 110,

                // left side
                160, 160, 220,
                160, 160, 220,
                160, 160, 220,
                160, 160, 220,
                160, 160, 220,
                160, 160, 220]),
            gl.STATIC_DRAW);
    }
}




new Main().start();
// new LeetCode1().start();
new MatchMaker2().start();

